﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DynaPrecision.Numerical
{
	using FunctionAnalysis;
	public class BisectionSolver<TInput, TResult> : IFunctionSolver<TInput, TResult>
	{
		public TInput LeftBound { get; set; }
		public TInput RightBound { get; set; }
		public TInput Resolution { get; set; }
		public BisectionSolver()
		{
			LeftBound = DefaultValueProvider<TInput>.GetZero();
			RightBound = DefaultValueProvider<TInput>.GetValueFromInteger(1);
			Resolution = DefaultValueProvider<TInput>.GetDefaultResolution();
		}
		public TInput SolveFor(Func<TInput, TResult> functor, TInput leftBound, TInput rightBound, TResult RightHandSide)
		{
			dynamic lb = leftBound;
			dynamic rb = rightBound;
			dynamic rr = RightHandSide;
			dynamic fl = functor(lb) - rr;
			dynamic fr = functor(rb) - rr;
			dynamic mid = (lb + rb) / 2;
			dynamic fm = functor(mid) - rr;
			if (fl * fr >= 0) throw new Exception("Bisection solver cannot find soltuion!");
			while (rb - lb >= Resolution)
			{
				if (fl == 0) return lb;
				else if (fr == 0) return rb;
				else if (fm == 0) return mid;
				if( fl * fm >= 0)
				{
					lb = mid;
					mid = (lb + rb) / 2;
					fl = functor(lb) -rr;
					fm = functor(mid) -rr;
				}
				else if (fm * fr >= 0)
				{
					rb = mid;
					mid = (lb + rb) / 2;
					fr = functor(rb) -rr;
					fm = functor(mid) -rr;
				}
			}
			return mid;
		}

		public TInput SolveFor<TFunction>(TFunction functor, TResult RighthandSide) where TFunction : IFunction<TInput, TResult>
		{
			throw new NotImplementedException();
		}
	}
}
